/*
 *
 *  Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
 *  SPDX-License-Identifier: Apache-2.0
 *
 */
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  Alert,
  Button,
  Card,
  Form,
  H3,
  Input,
  Justify,
  Layout,
  List,
  Select,
  SelectOptionWithGroup,
} from 'tea-component';
import { Controller, useForm, useWatch } from 'react-hook-form';
import formUtils, { Validator } from '../../utils/form-utils';
import { useGotoClick, useQueryParams } from '../../utils/hooks';
import {
  useChainSubscribe,
  useFetchCertOrgList,
  useFetchCertUserList,
  useFetchChainModes,
  useFetchChainSubscribeConfig,
} from '../../common/apis/chains/hooks';
import { ChainSubscribeRequest } from '../../common/apis/chains/interface';
import GlossaryGuide from '../../common/components/glossary-guide';
import { Col, Row, Switch } from 'tea-component/es';
import { omit } from '../../utils/common';

const { Content } = Layout;

export function ChainSubscribeContent(props: {
  cancelBtnText: string;
  cancelBtnClick: () => void;
  submitBtnText: string;
}) {
  const queryParams = useQueryParams<{
    chainId: string;
    chainName: string;
  }>();
  const gotoOrganization = useGotoClick('/certificates?tab=organization');
  const gotoNode = useGotoClick('/certificates?tab=node');
  const gotoUser = useGotoClick('/certificates?tab=user');
  const {
    control,
    setValue,
    reset,
    trigger,
    formState: { isValidating, isSubmitted, isValid },
    getValues,
  } = useForm({
    mode: 'onChange',
    defaultValues: {
      Tls: true,
      OrgId: '',
      TLSHostName: 'chainmaker.org',
    } as any,
  });
  // const [isPopulatedConfig, setIsPopulatedConfig] = useState(false); // 标记是否是拉取指定chainId的配置
  // const [selectOrg, setSelectOrg] = useState(0);
  const [isDirectSubscribe] = useState<boolean>(!!queryParams.chainId);
  const [orgOptions, setOrgOptions] = useState<SelectOptionWithGroup[]>([]);
  const [nodeOptions, setNodeOptions] = useState<SelectOptionWithGroup[]>([]);
  const [userOptions, setUserOptions] = useState<SelectOptionWithGroup[]>([]);
  const selectedOrgId = useWatch({ name: 'OrgId', control });
  const selectedChainMode = useWatch({ name: 'ChainMode', control });
  const isTls = useWatch({ name: 'Tls', control });
  const { run: fetchChainSubscribe, res: chainSubscribeRes } = useChainSubscribe();
  const goChains = useGotoClick('/chains');
  const handleSaveClick = useCallback(() => {
    const values = getValues();
    const form = {
      ChainId: values.ChainId,
      ChainMode: values.ChainMode,
      NodeRpcAddress: values.NodeRpcAddress,
    } as unknown as ChainSubscribeRequest;
    if (values.ChainMode === 'permissionedWithCert') {
      form.UserName = values.UserName;
      form.Tls = values.Tls ? 0 : 1;
      form.OrgId = values.OrgId;
      if (values.Tls) {
        form.TLSHostName = values.TLSHostName;
      }
    } else {
      form.AdminName = values.UserName;
    }
    fetchChainSubscribe(form);
  }, []);

  useEffect(() => {
    if (chainSubscribeRes === 'OK') {
      goChains();
    }
  }, [chainSubscribeRes]);

  const { list: chainModes, run: fetchChainModes } = useFetchChainModes();
  // const { pkNodeList, run: fetchPkNodeList } = useFetchCertNodeList();

  const chainModesOptions = useMemo(() => {
    const result = chainModes.map((item) => ({
      value: item.ChainMode,
      text: `${item.ChainModeName}(${item.ChainMode})`,
    }));
    return result;
  }, [chainModes]);

  const { orgList, run: fetchOrgList } = useFetchCertOrgList();
  useEffect(() => {
    setOrgOptions(orgList.map((item) => ({ value: item.OrgId, text: item.OrgName })));
  }, [orgList]);
  const { list: userList, run: fetchCertUserList } = useFetchCertUserList();
  useEffect(() => {
    setUserOptions(userList.map((user) => ({ value: user.UserName })));
  }, [userList]);

  const { run: fetchSubscribeConfig, data: chainConfig } = useFetchChainSubscribeConfig();

  const updateChainFormSelect = useCallback(() => {
    if (chainConfig?.Org) {
      const sOrg = chainConfig.Org.find((item) => item.OrgId === selectedOrgId);
      if (sOrg) {
        setNodeOptions(sOrg.NodeRpcAddress?.map((item) => ({ value: item })));
        setUserOptions(sOrg.UserName?.map((item) => ({ value: item })));
      }
    }
  }, [selectedOrgId, chainConfig]);
  const updateChainPkFormSelect = useCallback(() => {
    if (chainConfig?.Org) {
      const sOrg = chainConfig.Org[0];
      if (sOrg) {
        setNodeOptions(sOrg.NodeRpcAddress?.map((item) => ({ value: item })));
        setUserOptions(sOrg.AdminName ? sOrg.AdminName.map((item) => ({ value: item })) : []);
      }
    }
  }, [chainConfig]);
  useEffect(() => {
    if (isDirectSubscribe) {
      setValue('ChainMode', chainConfig?.ChainMode);
    } else {
      setValue('ChainMode', chainModesOptions[0]?.value);
    }
  }, [chainModesOptions]);
  useEffect(() => {
    if (!isDirectSubscribe) {
      return;
    }
    setValue('OrgId', orgOptions[0]?.value);
  }, [orgOptions]);
  useEffect(() => {
    if (nodeOptions.length === 0 || !isDirectSubscribe) {
      return;
    }
    setValue('NodeRpcAddress', nodeOptions[0]?.value);
    trigger('NodeRpcAddress');
  }, [nodeOptions]);
  useEffect(() => {
    if (!isDirectSubscribe) {
      return;
    }
    setValue('UserName', '');
  }, [userOptions]);
  const updateFormUsers = useCallback(() => {
    if (selectedChainMode === 'permissionedWithCert') {
      if (selectedOrgId) {
        fetchCertUserList({ OrgId: selectedOrgId, ChainMode: selectedChainMode });
      }
    } else {
      fetchCertUserList({ ChainMode: selectedChainMode });
    }
  }, [selectedOrgId, selectedChainMode]);
  useEffect(() => {
    if (isDirectSubscribe) {
      updateChainFormSelect();
    } else {
      updateFormUsers();
    }
  }, [selectedOrgId]);

  useEffect(() => {
    if (!isDirectSubscribe) {
      updateFormUsers();
    }
  }, [selectedChainMode]);

  useEffect(() => {
    if (isDirectSubscribe) {
      fetchSubscribeConfig(queryParams.chainId);
    } else {
      fetchOrgList();
    }
  }, [queryParams]);

  useEffect(() => {
    fetchChainModes();
  }, []);

  useEffect(() => {
    if (chainConfig) {
      const form: any = {
        ...omit(chainConfig, ['Org']),
      };
      if (chainConfig.ChainMode === 'permissionedWithCert') {
        form.Tls = !chainConfig.Tls;
        if (form.Tls) {
          form.TLSHostName = 'chainmaker.org';
        }
        setOrgOptions(chainConfig.Org.map((item) => ({ value: item.OrgId, text: item.OrgName })));
      } else {
        updateChainPkFormSelect();
      }
      reset(form);
    }
  }, [chainConfig]);

  return (
    <>
      <Row>
        <Col span={12}>
          <Alert>
            <List type="number">
              <List.Item>
                本处配置的节点，将用于监听链的信息，以及往链上发送交易，请配置该链上的节点，并确保稳定运行。
              </List.Item>
              <List.Item>
                本处配置的用户，将在后续往链上发送交易时，用于交易签名，请配置该链上的用户，以确保签名有效。
              </List.Item>
              <List.Item>
                若您要监听的链的证书不是通过本平台生成的，则请先导入相关
                <Button className={'text-deep-blue'} type={'link'} onClick={gotoOrganization}>
                  组织证书
                </Button>
                ，
                <Button className={'text-deep-blue'} type={'link'} onClick={gotoNode}>
                  节点证书
                </Button>
                ，
                <Button className={'text-deep-blue'} type={'link'} onClick={gotoUser}>
                  用户证书
                </Button>
                等，再配置。
              </List.Item>
            </List>
          </Alert>
          <Form layout="fixed" fixedLabelWidth={100}>
            <Controller
              control={control}
              rules={{
                validate: Validator.validateChainId,
              }}
              name="ChainId"
              render={({ field, fieldState }) => (
                <Form.Item
                  label="链ID"
                  required
                  status={formUtils.getStatus({
                    fieldState,
                    isValidating,
                    isSubmitted,
                  })}
                  message={fieldState.error?.message}
                >
                  <Input disabled={isDirectSubscribe} autoComplete="off" placeholder="请输入链ID" {...field} />
                </Form.Item>
              )}
            />
            <Controller
              control={control}
              rules={{
                required: true,
              }}
              name="ChainMode"
              render={({ field, fieldState }) => (
                <Form.Item
                  status={formUtils.getStatus({
                    fieldState,
                    isValidating,
                    isSubmitted,
                  })}
                  required
                  label="链账户模式"
                >
                  <Select disabled={isDirectSubscribe} options={chainModesOptions} {...field} />
                </Form.Item>
              )}
            />
            {selectedChainMode === 'permissionedWithCert' && (
              <Controller
                control={control}
                rules={{
                  required: true,
                }}
                name="OrgId"
                render={({ field, fieldState }) => (
                  <Form.Item
                    status={formUtils.getStatus({
                      fieldState,
                      isValidating,
                      isSubmitted,
                    })}
                    required
                    label="组织名称"
                  >
                    <Select options={orgOptions} {...field} />
                  </Form.Item>
                )}
              />
            )}
            <Controller
              control={control}
              rules={{
                validate: Validator.validateNodeIP,
              }}
              name="NodeRpcAddress"
              render={({ field, fieldState }) => (
                <Form.Item
                  label="节点RPC地址"
                  required
                  status={formUtils.getStatus({
                    fieldState,
                    isValidating,
                    isSubmitted,
                  })}
                  message={fieldState.error?.message}
                >
                  {isDirectSubscribe ? (
                    <Select options={nodeOptions} {...field} />
                  ) : (
                    <Input autoComplete="off" placeholder="请输入所选节点部署的IP和端口" {...field} />
                  )}
                </Form.Item>
              )}
            />
            <Controller
              control={control}
              name="UserName"
              rules={{
                required: true,
                validate: (value: string) => {
                  if (!value?.length) {
                    return '请选择用户';
                  }
                  return undefined;
                },
              }}
              render={({ field, fieldState }) => (
                <Form.Item
                  required
                  status={formUtils.getStatus({
                    fieldState,
                    isValidating,
                    isSubmitted,
                  })}
                  label={selectedChainMode === 'permissionedWithCert' ? '用户名称' : '管理员'}
                >
                  <Select options={userOptions} {...field} />
                </Form.Item>
              )}
            />{' '}
            {selectedChainMode === 'permissionedWithCert' && (
              <Controller
                control={control}
                name="Tls"
                render={({ field }) => (
                  <Form.Item label={<GlossaryGuide title={'是否开启TLS'} />}>
                    <Switch disabled={isDirectSubscribe} {...field} />
                  </Form.Item>
                )}
              />
            )}
            {/* {selectedChainMode === 'permissionedWithCert' && isTls && (
              <Controller
                control={control}
                name="TLSHostName"
                render={({ field }) => (
                  <Form.Item label="TLS_Host_Name">
                    <Input disabled={isDirectSubscribe} {...field} />
                  </Form.Item>
                )}
              />
            )} */}
          </Form>
          <Justify
            className={'tea-mt-5n'}
            left={
              <>
                <Button onClick={props.cancelBtnClick}>{props.cancelBtnText}</Button>
                <Button type="primary" onClick={handleSaveClick} disabled={!isValid}>
                  {props.submitBtnText}
                </Button>
              </>
            }
          />
        </Col>
        <Col span={12}>
          <Alert.Notice defaultOpen title={'常见问题'}>
            {selectedChainMode === 'permissionedWithCert' ? (
              <List type="number">
                <List.Item>如果发现管理平台区块高度落后于链的情况，请重新订阅。</List.Item>
                <List.Item>
                  订阅链失败，请检查您所填写的参数是否正确：
                  <List type="bullet">
                    <List.Item>所订阅的链是否已启动。</List.Item>
                    <List.Item>所填写的链节点网络是否通畅，端口是否开放。</List.Item>
                    <List.Item>所订阅的链的节点ip和端口是否与生成链配置时填写的一致。</List.Item>
                    <List.Item>链是否为容器启动，容器启动的链不能用容器启动的管理台订阅，因为网络是不通的。</List.Item>
                    <List.Item>所选择的账户模式是否正确。</List.Item>
                    <List.Item>TLS是否选择正确。</List.Item>
                  </List>
                </List.Item>
                <List.Item>
                  订阅链失败，证书错误，请检查用户证书是否正确：
                  <List type="bullet">
                    <List.Item>
                      一般导入外部链容易出现，请检查是否全部证书导入正常，是否和链使用的证书为同一套。
                    </List.Item>
                  </List>
                </List.Item>

                <List.Item>
                  订阅链失败，tls握手失败，请检查证书是否正确：
                  <List type="bullet">
                    <List.Item>一般导入外部链容易出现，请检查TLS证书是否正确导入，是否是订阅组织下的用户。</List.Item>
                  </List>
                </List.Item>
                <List.Item>
                  订阅链失败，chainId错误，请检查chainId是否正确：
                  <List type="bullet">
                    <List.Item>一般导入外部链容易出现，请检查订阅的输入chainid和外部链是否一致。</List.Item>
                  </List>
                </List.Item>
                <List.Item>如果按上述自测还是未解决问题，请检查管理台日志以及链相关日志，并到社区提问。</List.Item>
              </List>
            ) : (
              <List type="number">
                <List.Item>如果发现管理平台区块高度落后于链的情况，请重新订阅。</List.Item>
                <List.Item>
                  订阅链失败，请检查您所填写的参数是否正确：
                  <List type="bullet">
                    <List.Item>所订阅的链是否已启动。</List.Item>
                    <List.Item>所填写的链节点网络是否通畅，端口是否开放。</List.Item>
                    <List.Item>所订阅的链的节点ip和端口是否与生成链配置时填写的一致。</List.Item>
                    <List.Item>所选择的账户模式是否正确。</List.Item>
                    <List.Item>链是否为容器启动，容器启动的链不能用容器启动的管理台订阅，因为网络是不通的。</List.Item>
                  </List>
                </List.Item>
                <List.Item>订阅链失败，chainId错误，请检查chainId是否正确。</List.Item>
                <List.Item>如果按上述自测还是未解决问题，请检查管理台日志以及链相关日志，并到社区提问。</List.Item>
              </List>
            )}
          </Alert.Notice>
        </Col>
      </Row>
    </>
  );
}

export default function ChainSubscribe() {
  const handleBackClick = useGotoClick('/chains');
  return (
    <Content>
      <Content.Header title="区块链管理/订阅链" showBackButton onBackButtonClick={handleBackClick} />
      <Content.Body full>
        <Card>
          <Card.Header>
            <H3>配置监控节点</H3>
          </Card.Header>
          <Card.Body>
            <ChainSubscribeContent cancelBtnText={'取消'} submitBtnText={'保存'} cancelBtnClick={handleBackClick} />
          </Card.Body>
        </Card>
      </Content.Body>
    </Content>
  );
}
